package com.spsa.negocio.servicios;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;

import com.spsa.excepciones.EstadoIlegalExcepcion;
import com.spsa.excepciones.GuardarDatosException;
import com.spsa.excepciones.RecuperarDatosException;
import com.spsa.excepciones.ServicioException;
import com.spsa.negocio.utilidades.EstadoArchivo;
import com.spsa.negocio.utilidades.SingletonDatos;
import com.spsa.persistencia.dao.EstadoInterfazDao;
import com.spsa.persistencia.entidades.EstadoInterfaz;
import com.spsa.persistencia.entidades.Interfaz;
import com.spsa.persistencia.entidades.Tienda;

@Stateless
public class ServicioEstadosTiendas {

	static final Logger logger = LogManager.getLogger(ServicioEstadosTiendas.class.getName());

	@EJB
	private EstadoInterfazDao estadoInterfazDao;
	@EJB
	private SingletonDatos singletonDatos;

	public void validarYGuardar(EstadoInterfaz estadoInterfaz) throws ServicioException {
		try {
			String descripcionInterfaz = estadoInterfaz.getDescripcionInterfaz();
			String codigoTienda = estadoInterfaz.getCodigoTienda();

			if (!singletonDatos.existeInterfaz(descripcionInterfaz) || !singletonDatos.existeTienda(codigoTienda)) {
				logger.error("Se encontro un mensaje con tienda o interfaz no valida", estadoInterfaz);
				return;
			}
			if (!singletonDatos.buscarTienda(codigoTienda).getInterfaces()
					.contains(singletonDatos.buscarInterfaz(descripcionInterfaz))) {
				logger.error("Se encontro un mensaje asociado a una interfaz no valida de una tienda", estadoInterfaz);
				return;
			}

			estadoInterfaz.setFechaProcesamiento(DateTime.now().toDate());
			estadoInterfazDao.guardarOrActualizar(estadoInterfaz);
		} catch (EstadoIlegalExcepcion e) {
			throw new ServicioException("No se encontro informacion sobre la tienda o la interfaz");
		} catch (GuardarDatosException e) {
			throw new ServicioException("No se pudo procesar el mensaje");
		}
	}

	public int cantidadEstados(List<EstadoInterfaz> estados, EstadoArchivo estadoArchivos) {
		int cantidadTiendas = 0;

		for (int i = 0; i < estados.size(); i++) {
			if (singletonDatos.tiendaEstaActiva(estados.get(i).getCodigoTienda())
					&& estados.get(i).getEstadoArchivos() == estadoArchivos)
				cantidadTiendas++;
		}

		return cantidadTiendas;
	}

	public List<EstadoInterfaz> listarPorInterfaz(Interfaz interfaz) throws ServicioException {
		try {
			Date fecha = LocalDate.now().toDate();
			List<EstadoInterfaz> estados = new ArrayList<EstadoInterfaz>(estadoInterfazDao.obtenerEstados(fecha,
					interfaz));
			completarEstadoFaltantes(interfaz, estados);
			return estados;
		} catch (RecuperarDatosException e) {
			throw new ServicioException("No se pudo recuperar los estados de las tiendas de la interfaz "
					+ interfaz.getDescripcion());
		}
	}

	private void completarEstadoFaltantes(Interfaz interfaz, List<EstadoInterfaz> estados) {
		EstadoInterfaz estadoInterfaz;
		List<Tienda> tiendas = singletonDatos.getTiendas();

		for (int i = 0; i < tiendas.size(); i++) {
			if (!existeEstadoParaLaTienda(tiendas.get(i), estados)) {
				estadoInterfaz = crearEstadoInterfazDefecto(tiendas.get(i), interfaz);
				estados.add(estadoInterfaz);
			}
		}
	}

	private EstadoInterfaz crearEstadoInterfazDefecto(Tienda tienda, Interfaz interfaz) {
		EstadoInterfaz estadoInterfaz = new EstadoInterfaz();
		estadoInterfaz.setCodigoTienda(tienda.getCodigo());
		estadoInterfaz.setDescripcionInterfaz(interfaz.getDescripcion());
		estadoInterfaz.setEstadoArchivos(EstadoArchivo.NO_SE_ENCONTRO_NADA);
		estadoInterfaz.setFechaUso(LocalDate.now().toDate());
		estadoInterfaz.setFechaProcesamiento(DateTime.now().toDate());
		return estadoInterfaz;
	}

	public void ordenarPorPrioridad(List<EstadoInterfaz> estados) {
		Collections.sort(estados, new Comparator<EstadoInterfaz>() {

			@Override
			public int compare(EstadoInterfaz estadoInterfaz1, EstadoInterfaz estadoInterfaz2) {
				int peso1 = estadoInterfaz1.getEstadoArchivos().getValor();
				int peso2 = estadoInterfaz2.getEstadoArchivos().getValor();

				return peso1 - peso2;
			}

		});
	}

	private boolean existeEstadoParaLaTienda(Tienda tienda, List<EstadoInterfaz> estados) {
		for (int i = 0; i < estados.size(); i++) {
			if (estados.get(i).getCodigoTienda().equals(tienda.getCodigo()))
				return true;
		}

		return false;
	}

	public void marcarEstados(List<EstadoInterfaz> estados) {
		for(int i = 0; i < estados.size(); i ++) {
			estados.get(i).setMarcado(true);
		}
	}

	public void guardarOActualizar(List<EstadoInterfaz> estados) throws GuardarDatosException {
		for(int i = 0; i < estados.size(); i ++) {
			estadoInterfazDao.guardarOrActualizar(estados.get(i));
		}
	}
}
